package tx.algoritmiek.week2;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Random;

public class BinaryTreeBenchmark {

	private GameObject[] gameObjects;
	private BinaryTree tree;
	private GameObject searchFor;

	public BinaryTreeBenchmark(int treeSize) {
		if (treeSize <= 0) {
			throw new IllegalArgumentException(
					"Tree size must be greater than zero.");
		}
		this.gameObjects = new GameObject[treeSize];
	}

	private void createGameObjects() {
		// Random generator
		Random random = new Random(Calendar.getInstance().getTimeInMillis());
		// Maximum coordinate value
		int max = 1000;

		for (int i = 0; i < this.gameObjects.length; i++) {
			// Create object
			this.gameObjects[i] = new GameObject(random.nextInt(max) + 1,
					random.nextInt(max) + 1);

		}
		// Set as the object to search for
		this.searchFor = this.gameObjects[this.gameObjects.length - 1];
	}

	public void benchmarkCustomBinaryTree() {
		long timeBefore, timeAfter, totalTime;

		System.out.println("Benchmarking BinaryTree");

		totalTime = Calendar.getInstance().getTimeInMillis();

		System.out.print("Creating tree data...");
		timeBefore = Calendar.getInstance().getTimeInMillis();
		this.createGameObjects();
		timeAfter = Calendar.getInstance().getTimeInMillis();
		System.out.println(" done in " + (timeAfter - timeBefore) + " ms");

		System.out.print("Sorting tree...");
		timeBefore = Calendar.getInstance().getTimeInMillis();
		this.tree = new BinaryTree(
				new QuickSortAlgorithm().sortGameObjects(this.gameObjects));
		this.tree.setBoundArraysInTree();
		timeAfter = Calendar.getInstance().getTimeInMillis();
		System.out.println(" done in " + (timeAfter - timeBefore) + " ms");

		// Get coordinates to find
		int[] coordinates = { (int) this.searchFor.getPosition(0),
				(int) this.searchFor.getPosition(1) };

		System.out.println("Searching objects with coordinates: "
				+ coordinates[0] + ", " + coordinates[1] + "...");
		timeBefore = Calendar.getInstance().getTimeInMillis();
		// Find coordinates
		List<GameObject> result = this.tree.find(coordinates);
		timeAfter = Calendar.getInstance().getTimeInMillis();
		System.out.println(" done in " + (timeAfter - timeBefore) + " ms");

		System.out.println("Items found (" + result.size() + "):");
		for (GameObject g : result) {
			System.out.println(g.getPosition(0) + ", " + g.getPosition(1));
		}

		totalTime = Calendar.getInstance().getTimeInMillis() - totalTime;

		System.out.println("Total execution time: " + totalTime + " ms");
		System.out.println("-----------");
	}

	public void benchmarkArray() {
		long timeBefore, timeAfter, totalTime;

		System.out.println("Benchmarking array");

		totalTime = Calendar.getInstance().getTimeInMillis();

		System.out.print("Creating tree data...");
		timeBefore = Calendar.getInstance().getTimeInMillis();
		this.createGameObjects();
		timeAfter = Calendar.getInstance().getTimeInMillis();
		System.out.println(" done in " + (timeAfter - timeBefore) + " ms");

		// Get coordinates to find
		int[] coordinates = { (int) this.searchFor.getPosition(0),
				(int) this.searchFor.getPosition(1) };

		List<GameObject> result = new ArrayList<GameObject>();

		System.out.print("Searching objects with coordinates: "
				+ coordinates[0] + ", " + coordinates[1] + "...");
		timeBefore = Calendar.getInstance().getTimeInMillis();
		// Find coordinates
		for (GameObject g : this.gameObjects) {
			if (g.getPosition(0) == this.searchFor.getPosition(0)
					&& g.getPosition(1) == this.searchFor.getPosition(1)) {
				result.add(g);
			}
		}
		timeAfter = Calendar.getInstance().getTimeInMillis();
		System.out.println(" done in " + (timeAfter - timeBefore) + " ms");

		System.out.println("Items found (" + result.size() + "):");
		for (GameObject g : result) {
			System.out.println(g.getPosition(0) + ", " + g.getPosition(1));
		}

		totalTime = Calendar.getInstance().getTimeInMillis() - totalTime;

		System.out.println("Total execution time: " + totalTime + " ms");
		System.out.println("-----------");
	}

	public void benchmarkExistingBinaryTree() {

	}
}
